﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SQLite;
using System.IO;
using System.Configuration;
using System.Data;
using System.Windows.Forms;
using GS1.Entidad;

namespace GS1.Dato
{
    public class DatosLite : IDisposable
    {
        #region --- Variables Privadas ---
        private SQLiteDataAdapter adapter;
        private SQLiteCommand comando;
        private SQLiteConnection conexion;

        private static string NOMBRE_REPOSITORIO = "Repositorio";
        #endregion

        #region --- Constructor y Destructor ---
        public DatosLite()
        {
            string sRutaBD = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + ConfigurationManager.AppSettings[NOMBRE_REPOSITORIO];

            conexion = new SQLiteConnection(string.Format("Data Source={0};New={1};Compress=False;Version={2};PRAGMA journal_mode=WAL;", sRutaBD,
                                                                                                                 false,
                                                                                                                 3));
        }

        public void Dispose()
        {
            if (this.conexion != null)
            {
                if (this.conexion.State == ConnectionState.Open)
                {
                    this.conexion.Close();
                }
                this.conexion.Dispose();
            }
            this.conexion = null;
        }
        #endregion

        #region --- Procedimientos Genericos ---

        public DataTable GEN_Consulta(string pCadSQL, string pNombreTabla)
        {
            DataTable dataTable = new DataTable(pNombreTabla);
            if (this.conexion.State == ConnectionState.Open)
            {
                this.conexion.Close();
            }
            try
            {
                this.adapter = new SQLiteDataAdapter(pCadSQL, this.conexion);
                this.adapter.Fill(dataTable);
            }
            catch (SQLiteException exception1)
            {
                throw (exception1);
            }
            catch (Exception exception3)
            {
                throw (exception3);
            }
            finally
            {
                this.adapter.Dispose();
            }
            return dataTable;
        }

        public DataSet GEN_Consulta(string pCadSQL)
        {
            DataSet oData = new DataSet();
            if (this.conexion.State == ConnectionState.Open) { this.conexion.Close(); }

            try
            {
                this.adapter = new SQLiteDataAdapter(pCadSQL, this.conexion);
                this.adapter.Fill(oData);
            }
            catch (SQLiteException exception1)
            {
                throw (exception1);
            }
            catch (Exception exception3)
            {
                throw (exception3);
            }
            finally
            {
                this.adapter.Dispose();
            }
            return oData;
        }

        public bool GEN_EjecutaComando(SQLiteConnection pConexion, string pComandoTxt)
        {
            this.comando = new SQLiteCommand();
            try
            {
                this.comando.Connection = pConexion;
                this.comando.CommandText = pComandoTxt;
                this.comando.CommandType = CommandType.Text;
                this.conexion = this.ConectarBD();
                this.comando.ExecuteNonQuery();
            }
            catch (SQLiteException exception1)
            {
                throw (exception1);
            }
            catch (Exception exception3)
            {
                throw (exception3);
            }
            finally
            {
                this.conexion.Close();
                this.comando.Dispose();
                this.comando = null;
            }
            return false;
        }

        #endregion

        #region --- ConexionBD ---
        private SQLiteConnection ConectarBD()
        {
            if (this.conexion.State == ConnectionState.Closed)
            {
                this.conexion.Open();
            }
            return this.conexion;
        }

        #endregion

        #region --- Procedimientos BD ---

        public bool guardarMovimientoControlVehiculo(ControlVehiculoRFID controlVehiculoRFID)
        {
            bool resultado = false;
            StringBuilder cadenaSQL = null;
            SQLiteTransaction transaction = null;

            try
            {
                cadenaSQL = new StringBuilder();
                cadenaSQL.Append("INSERT INTO CONTROLVEHICULO (codigoEPC, codigoDireccionVehiculo, descripcionPuerta, fechaInicioMovimiento, fechaFinalMovimiento) ");
                cadenaSQL.Append("VALUES (?, ?, ?, ?, ?)");

                this.comando = new SQLiteCommand();
                this.conexion = this.ConectarBD();
                transaction = this.conexion.BeginTransaction();

                this.comando.Connection = this.conexion;
                this.comando.CommandText = cadenaSQL.ToString();
                this.comando.CommandType = CommandType.Text;

                this.comando.Prepare();

                this.comando.Parameters.Add("codigoEPC", DbType.String);
                this.comando.Parameters.Add("codigoDireccionVehiculo", DbType.String);
                this.comando.Parameters.Add("descripcionPuerta", DbType.String);
                this.comando.Parameters.Add("fechaInicioMovimiento", DbType.DateTime);
                this.comando.Parameters.Add("fechaFinalMovimiento", DbType.DateTime);

                this.comando.Parameters["codigoEPC"].Value = controlVehiculoRFID.codigoEPC;
                this.comando.Parameters["codigoDireccionVehiculo"].Value = controlVehiculoRFID.codigoDireccionVehiculo;
                this.comando.Parameters["descripcionPuerta"].Value = controlVehiculoRFID.descripcionPuerta;
                this.comando.Parameters["fechaInicioMovimiento"].Value = controlVehiculoRFID.fechaInicioMovimiento;
                this.comando.Parameters["fechaFinalMovimiento"].Value = controlVehiculoRFID.fechaFinalMovimiento;

                this.comando.ExecuteNonQuery();

                transaction.Commit();

                resultado = true;
            }
            finally
            {
                if ((this.comando != null) && (this.comando.Connection != null))
                {
                    this.comando.Connection.Close();
                }
                this.conexion.Close();
            }
            return resultado;
        }

        public bool validarMovimientoControlVehiculo(ControlVehiculoRFID controlVehiculoRFID)
        {
            DataTable tablaResultado = null;
            StringBuilder cadenaSQL = null;

            cadenaSQL = new StringBuilder();
            cadenaSQL.Append("SELECT codigoEPC, codigoDireccionVehiculo, descripcionPuerta, fechaInicioMovimiento, fechaFinalMovimiento ");
            cadenaSQL.Append("FROM CONTROLVEHICULO ");
            cadenaSQL.Append("WHERE codigoEPC = '" + controlVehiculoRFID.codigoEPC + "' ");
            cadenaSQL.Append("AND codigoDireccionVehiculo = '" + controlVehiculoRFID.codigoDireccionVehiculo + "' ");
            cadenaSQL.Append("AND descripcionPuerta = '" + controlVehiculoRFID.descripcionPuerta + "' ");
            cadenaSQL.Append("AND fechaInicioMovimiento = '" + controlVehiculoRFID.fechaInicioMovimiento + "' ");
            cadenaSQL.Append("AND fechaFinalMovimiento = '" + controlVehiculoRFID.fechaFinalMovimiento + "' ");

            tablaResultado = this.GEN_Consulta(cadenaSQL.ToString(), "TablaMovimiento");

            return tablaResultado.Rows.Count > 0;
        }

        public bool eliminarMovimientoControlVehiculo(DateTime dia)
        {
            bool resultado = false;
            StringBuilder cadenaSQL = null;
            SQLiteTransaction transaction = null;

            try
            {
                cadenaSQL = new StringBuilder();
                cadenaSQL.Append("DELETE FROM CONTROLVEHICULO ");
                cadenaSQL.Append("WHERE fechaInicioMovimiento < '" + dia.ToString("yyyy-MM-dd HH:mm:ss") + "' ");

                this.comando = new SQLiteCommand();
                this.conexion = this.ConectarBD();
                transaction = this.conexion.BeginTransaction();

                this.comando.Connection = this.conexion;
                this.comando.CommandText = cadenaSQL.ToString();
                this.comando.CommandType = CommandType.Text;

                this.comando.ExecuteNonQuery();

                transaction.Commit();

                resultado = true;
            }
            finally
            {
                if ((this.comando != null) && (this.comando.Connection != null))
                {
                    this.comando.Connection.Close();
                }
                this.conexion.Close();
            }
            return resultado;
        }

        public bool modificarMovimientoControlVehiculo(ControlVehiculoRFID controlVehiculoRFID)
        {
            bool resultado = false;
            StringBuilder cadenaSQL = null;
            SQLiteTransaction transaction = null;

            try
            {
                cadenaSQL = new StringBuilder();
                cadenaSQL.Append("UPDATE CONTROLVEHICULO SET estado = '0' ");
                cadenaSQL.Append("WHERE codigoEPC = '" + controlVehiculoRFID.codigoEPC + "' ");
                cadenaSQL.Append("AND estado = '1' ");

                this.comando = new SQLiteCommand();
                this.conexion = this.ConectarBD();
                transaction = this.conexion.BeginTransaction();

                this.comando.Connection = this.conexion;
                this.comando.CommandText = cadenaSQL.ToString();
                this.comando.CommandType = CommandType.Text;

                this.comando.ExecuteNonQuery();

                transaction.Commit();

                resultado = true;
            }
            finally
            {
                if ((this.comando != null) && (this.comando.Connection != null))
                {
                    this.comando.Connection.Close();
                }
                this.conexion.Close();
            }
            return resultado;
        }

        public ListaControlVehiculoRFID ListaRegistroListaTotalMovimientoControlVehiculo()
        {
            DataTable tablaResultado = null;
            StringBuilder cadenaSQL = null;
            ListaControlVehiculoRFID listaVehiculo = new ListaControlVehiculoRFID();

            cadenaSQL = new StringBuilder();
            cadenaSQL.Append("SELECT codigoEPC, codigoDireccionVehiculo, descripcionPuerta, fechaInicioMovimiento, fechaFinalMovimiento ");
            cadenaSQL.Append("FROM CONTROLVEHICULO ");
            cadenaSQL.Append("WHERE estado = '1' ");

            tablaResultado = this.GEN_Consulta(cadenaSQL.ToString(), "TablaTemporal");

            if (tablaResultado.Rows.Count > 0)
            {
                foreach (DataRow fila in tablaResultado.Rows)
                {
                    ControlVehiculoRFID controlVehiculo = new ControlVehiculoRFID();
                    controlVehiculo.codigoEPC = fila["codigoEPC"].ToString();
                    controlVehiculo.codigoDireccionVehiculo = Convert.ToInt32(fila["codigoDireccionVehiculo"]);
                    controlVehiculo.descripcionPuerta = fila["descripcionPuerta"].ToString();
                    controlVehiculo.fechaInicioMovimiento = Convert.ToDateTime(fila["fechaInicioMovimiento"]);
                    controlVehiculo.fechaFinalMovimiento = Convert.ToDateTime(fila["fechaFinalMovimiento"]);

                    listaVehiculo.Add(controlVehiculo);
                }
            }

            return listaVehiculo;
        }

        public bool guardarListaEtiqueta(Etiqueta etiqueta)
        {
            bool resultado = false;
            StringBuilder cadenaSQL = null;
            SQLiteTransaction transaction = null;

            try
            {
                cadenaSQL = new StringBuilder();
                cadenaSQL.Append("INSERT INTO LISTAETIQUETA (epc, tipo, antena, fechaInicio, fechafinal) ");
                cadenaSQL.Append("VALUES (?, ?, ?, ?, ?)");

                this.comando = new SQLiteCommand();
                this.conexion = this.ConectarBD();
                transaction = this.conexion.BeginTransaction();

                this.comando.Connection = this.conexion;
                this.comando.CommandText = cadenaSQL.ToString();
                this.comando.CommandType = CommandType.Text;

                this.comando.Prepare();

                this.comando.Parameters.Add("epc", DbType.String);
                this.comando.Parameters.Add("tipo", DbType.String);
                this.comando.Parameters.Add("antena", DbType.String);
                this.comando.Parameters.Add("fechaInicio", DbType.DateTime);
                this.comando.Parameters.Add("fechafinal", DbType.DateTime);

                this.comando.Parameters["epc"].Value = etiqueta.epc;
                this.comando.Parameters["tipo"].Value = etiqueta.tipo;
                this.comando.Parameters["antena"].Value = etiqueta.antena;
                this.comando.Parameters["fechaInicio"].Value = etiqueta.fechaInicio;
                this.comando.Parameters["fechafinal"].Value = etiqueta.fechaFinal;

                this.comando.ExecuteNonQuery();

                transaction.Commit();

                resultado = true;
            }
            finally
            {
                if ((this.comando != null) && (this.comando.Connection != null))
                {
                    this.comando.Connection.Close();
                }
                this.conexion.Close();
            }
            return resultado;
        }

        public ListaEtiqueta ListaRegistroUnicoEtiquetas()
        {
            DataTable tablaResultado = null;
            StringBuilder cadenaSQL = null;
            ListaEtiqueta listaEtiqueta = new ListaEtiqueta();

            cadenaSQL = new StringBuilder();
            cadenaSQL.Append("SELECT distinct epc ");
            cadenaSQL.Append("FROM LISTAETIQUETA ");
            cadenaSQL.Append("WHERE estado = '1' ");

            tablaResultado = this.GEN_Consulta(cadenaSQL.ToString(), "TablaTemporal");

            if (tablaResultado.Rows.Count > 0)
            {
                foreach (DataRow fila in tablaResultado.Rows)
                {
                    Etiqueta etiqueta = new Etiqueta();
                    etiqueta.epc = fila["epc"].ToString();

                    listaEtiqueta.Add(etiqueta);
                }
            }

            return listaEtiqueta;
        }

        public Etiqueta buscaUltimaLecturaEtiqueta(Etiqueta etiquetabuscada)
        {
            DataTable tablaResultado = null;
            StringBuilder cadenaSQL = null;
            Etiqueta Etiqueta = new Etiqueta();

            cadenaSQL = new StringBuilder();
            cadenaSQL.Append("SELECT epc, tipo, antena, fechaInicio, fechafinal ");
            cadenaSQL.Append("FROM LISTAETIQUETA ");
            cadenaSQL.Append("WHERE epc = '" + etiquetabuscada.epc + "' ");
            cadenaSQL.Append("AND fechafinal = (SELECT max(fechafinal) FROM LISTAETIQUETA WHERE epc =  '" + etiquetabuscada.epc + "' ) ");

            tablaResultado = this.GEN_Consulta(cadenaSQL.ToString(), "TablaTemporal");

            if (tablaResultado.Rows.Count > 0)
            {
                Etiqueta = cargaEtiqueta(tablaResultado.Rows[0]);
            }

            return Etiqueta;
        }

        public Etiqueta buscaPrimeraLecturaEtiqueta(Etiqueta etiquetabuscada)
        {
            DataTable tablaResultado = null;
            StringBuilder cadenaSQL = null;
            Etiqueta Etiqueta = new Etiqueta();

            cadenaSQL = new StringBuilder();
            cadenaSQL.Append("SELECT epc, tipo, antena, fechaInicio, fechafinal ");
            cadenaSQL.Append("FROM LISTAETIQUETA ");
            cadenaSQL.Append("WHERE epc = '" + etiquetabuscada.epc + "' ");
            cadenaSQL.Append("AND fechafinal = (SELECT min(fechafinal) FROM LISTAETIQUETA WHERE epc =  '" + etiquetabuscada.epc + "' ) ");

            tablaResultado = this.GEN_Consulta(cadenaSQL.ToString(), "TablaTemporal");

            if (tablaResultado.Rows.Count > 0)
            {
                Etiqueta = cargaEtiqueta(tablaResultado.Rows[0]);
            }

            return Etiqueta;
        }

        public Etiqueta cargaEtiqueta(DataRow fila)
        {
            Etiqueta etiquetaSalida = new Etiqueta();
            etiquetaSalida.epc = fila["epc"].ToString();
            etiquetaSalida.tipo = fila["tipo"].ToString();
            etiquetaSalida.antena = fila["antena"].ToString();
            etiquetaSalida.fechaInicio = Convert.ToDateTime(fila["fechaInicio"]);
            etiquetaSalida.fechaFinal = Convert.ToDateTime(fila["fechaFinal"]);

            return etiquetaSalida;
        }

        public bool eliminarListaEtiqueta(Etiqueta etiqueta)
        {
            bool resultado = false;
            StringBuilder cadenaSQL = null;
            SQLiteTransaction transaction = null;

            try
            {
                cadenaSQL = new StringBuilder();
                cadenaSQL.Append("DELETE FROM LISTAETIQUETA ");
                cadenaSQL.Append("WHERE epc = '" + etiqueta.epc + "' ");

                this.comando = new SQLiteCommand();
                this.conexion = this.ConectarBD();
                transaction = this.conexion.BeginTransaction();

                this.comando.Connection = this.conexion;
                this.comando.CommandText = cadenaSQL.ToString();
                this.comando.CommandType = CommandType.Text;

                this.comando.ExecuteNonQuery();

                transaction.Commit();

                resultado = true;
            }
            finally
            {
                if ((this.comando != null) && (this.comando.Connection != null))
                {
                    this.comando.Connection.Close();
                }
                this.conexion.Close();
            }
            return resultado;
        }

        public bool eliminarListaEtiquetaRemanente(DateTime dia)
        {
            bool resultado = false;
            StringBuilder cadenaSQL = null;
            SQLiteTransaction transaction = null;

            try
            {
                cadenaSQL = new StringBuilder();
                cadenaSQL.Append("DELETE FROM LISTAETIQUETA ");
                cadenaSQL.Append("WHERE fechaInicio < '" + dia.ToString("yyyy-MM-dd HH:mm:ss") + "' ");

                this.comando = new SQLiteCommand();
                this.conexion = this.ConectarBD();
                transaction = this.conexion.BeginTransaction();

                this.comando.Connection = this.conexion;
                this.comando.CommandText = cadenaSQL.ToString();
                this.comando.CommandType = CommandType.Text;

                this.comando.ExecuteNonQuery();

                transaction.Commit();

                resultado = true;
            }
            finally
            {
                if ((this.comando != null) && (this.comando.Connection != null))
                {
                    this.comando.Connection.Close();
                }
                this.conexion.Close();
            }
            return resultado;
        }

        #endregion

    }
}
